import argparse
import datetime
import time
import cv2
import requests

# 一年不拍照
capture_delay = 60 * 60 * 24 * 365

# 创建参数解析器并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", help="path to the video file")
args = vars(ap.parse_args())

# 如果video参数为None从摄像头读取数据，否则读取视频文件
if args.get("video", None) is None:
    camera = cv2.VideoCapture(0)
    time.sleep(0.25)
else:
    camera = cv2.VideoCapture(args["video"])

# 初始化视频流的第一帧
firstFrame = None
i = 0
buffer = datetime.datetime.now()
record_buffer = buffer
capture = False

FPS = 0
FPSBuffer = 0
lastTime = round(time.time())

upload = False
move_num = 0


def update(stuId):
    payload = {'stuId': stuId}
    r = requests.get('http://ali.lifanko.cn/idp/miao/update.php', params=payload)
    print(datetime.datetime.now().strftime("%B %d %I:%M:%S%p") + ' - update status code: ' + str(r.status_code))


# 遍历视频的每一帧
while True:
    thisTime = round(time.time())
    if thisTime != lastTime:
        lastTime = thisTime
        FPS = FPSBuffer
        FPSBuffer = 0
    else:
        FPSBuffer += 1

    # 获取当前帧并初始化occupied/unoccupied文本
    (grabbed, frame) = camera.read()
    text = "No"

    # 如果不能抓取到一帧，说明我们到了视频的结尾
    if not grabbed:
        break

    # 调整该帧的大小，转换为灰阶图像并且对其进行高斯模糊
    # frame = imutils.resize(frame, width=500)
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (21, 21), 10)

    # 如果第一帧是None，对其进行初始化
    if firstFrame is None:
        firstFrame = gray
        continue

    # 计算当前帧和第一帧的不同
    frameDelta = cv2.absdiff(firstFrame, gray)
    thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]

    # 扩展阀值图像填充孔洞，然后找到阀值图像上的轮廓
    thresh = cv2.dilate(thresh, None, iterations=2)
    (_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
                                    cv2.CHAIN_APPROX_SIMPLE)

    # 遍历轮廓
    for c in cnts:
        # 计算轮廓的边界框，在当前帧中画出该框
        (x, y, w, h) = cv2.boundingRect(c)
        # cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.circle(frame, (int(x + w / 2), int(y + h / 2)), int(min(w, h) / 2), (0, 255, 0), 1)

    if cnts:
        text = "Yes"

    # 在当前帧写上文字以及时间戳
    cv2.putText(frame, "DIFF: {}".format(text), (10, 20),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
    cv2.putText(frame,
                datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p") + ' FPS: ' + str(FPS) + ' Move Num: ' + str(
                    move_num), (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)

    # 显示当前帧
    cv2.imshow("Security Feed", frame)

    # 丢弃刚刚启动相机时不稳定的10帧图像
    if i < 10:
        i = i + 1
        if i == 10:
            firstFrame = None
    else:
        if text == 'Yes':
            if int(datetime.datetime.now().strftime('%y%m%d%H%M%S')) - int(buffer.strftime('%y%m%d%H%M%S')) >= 5:
                buffer = datetime.datetime.now()
                firstFrame = None
                capture = True
                upload = True
                move_num += 1

    if int(datetime.datetime.now().strftime('%y%m%d%H%M%S')) - int(record_buffer.strftime('%y%m%d%H%M%S')) >= 60:
        record_buffer = datetime.datetime.now()
        if upload and move_num > 6:
            update('311408001117')
        else:
            print('noUpload')
        upload = False
        move_num = 0

    # 检测到移动不立即拍照，延迟capture_delay后拍照
    if (int(datetime.datetime.now().strftime('%y%m%d%H%M%S')) - int(
            buffer.strftime('%y%m%d%H%M%S')) >= capture_delay) & capture:
        # 判断今天的文件夹是否已经存在，如果没有则进行创建
        dirName = buffer.strftime('%y-%m-%d')
        isExists = cv2.os.path.exists(dirName)
        if not isExists:
            cv2.os.mkdir(dirName)
        if text == 'Yes':
            cv2.imwrite(dirName + '/' + buffer.strftime('%H-%M-%S') + '.jpg', frame)
            print(dirName + '/' + buffer.strftime('%H-%M-%S') + '.jpg')
        else:
            print('Escape')
        capture = False

    key = cv2.waitKey(1) & 0xFF

    # 如果空格键被按下，结束程序
    if key == ord(" "):
        break

# 清理摄像机资源并关闭打开的窗口
camera.release()
cv2.destroyAllWindows()
